/*
 * Copyright (c) www.bugull.com
 */

package com.bugull.farm.device.server.processor;

import com.bugull.farm.core.cache.PropertiesCache;
import com.bugull.farm.core.client.BuguKeeperClient;
import com.bugull.farm.core.enums.EventType;
import com.bugull.farm.core.frame.exception.BuguException;
import com.bugull.farm.core.frame.structure.Frame;
import com.bugull.farm.core.handler.Processor;
import com.bugull.farm.core.server.FarmServer;
import com.bugull.farm.core.store.OnOffLineEventHistory;
import com.bugull.farm.core.utils.GetIPInfoCallable;
import com.bugull.farm.core.utils.GetIPInfoTask;
import com.bugull.farm.core.utils.IpUtil;
import com.bugull.farm.core.store.Device;
import com.bugull.farm.device.server.cache.DeviceCache;
import com.bugull.mongo.BuguDao;
import com.bugull.mongo.cache.DaoCache;
import com.bugull.redis.RedisConnection;
import com.bugull.redis.mq.MQClient;

import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;

import java.util.Date;

/**
 *
 * @author Frank Wen(xbwen@hotmail.com)
 */
public class DeviceJoinProcessor implements Processor {

	private PropertiesCache props = PropertiesCache.getInstance();
	
    @Override
    public void process(final ChannelHandlerContext ctx, Frame frame) throws Exception {
    	//处理设备接入请求
        String mac = frame.getHexStr("mac");
        String joinCode = frame.getHexStr("joincode");
        //校验接入码
        if(!joinCode.equals(PropertiesCache.getInstance().get("dev.join.code"))){
        	throw new BuguException(PropertiesCache.getInstance().getByte("error.identify"), frame.getRequest(), "Indentify check failed!!!");
        }
        String deviceType = frame.getHexStr("devicetype");
        String companyCode = frame.getHexStr("companycode");
        String authCode = frame.getHexStr("authCode");
        BuguDao<Device> dao = DaoCache.getInstance().get(Device.class);
        Device device = dao.findOne("macAddress", mac);
        //保存接入设备的基础信息
        if(device == null){
            device = new Device();
            device.setMacAddress(mac);
            device.setActiveTime(new Date());
            //report to BuguKeeper
//            BuguKeeperClient client = BuguKeeperClient.getInstance();
//            client.reportActivation(FarmConstant.BUGU_KEEPER_PROJECT, frame.getBytes("mac"), frame.getByte("companycode"), frame.getByte("devicetype"));
        }
        //deviceType and companyCode maybe changed, due to wifi module reuse
        device.setCompanyCode(companyCode);
        device.setDeviceType(deviceType);
        device.setAuthCode(authCode);
        device.setOnline(true);
        device.setLastOnlineTime(new Date());
        String ip = IpUtil.getRemoteIp(ctx);
        device.setLastOnlineIp(ip);
        device.setLoginIp(props.get("ip"));
        dao.save(device);

        //recode history
        recodeOnlineEvent(mac);

        //异步解析IP信息
        GetIPInfoTask getIPInfoTask = new GetIPInfoTask(new GetIPInfoCallable(mac, ip));
        FarmServer.getExecutors().submit(getIPInfoTask);
        
        //缓存设备和设备与服务器之间的连接通道
        DeviceCache.getInstance().addDev(mac, ctx.channel().id());
        //回复接入成功
        ctx.writeAndFlush(frame.getFastResponse()).addListener(new ChannelFutureListener(){
            @Override
            public void operationComplete(ChannelFuture future) throws Exception{
                if (future.isSuccess()) {
                    //接入成功后马上查询设备信息
                	ctx.writeAndFlush(frame.getQuery());
                }
            }
        });
        //发送上线通知
        MQClient client = RedisConnection.getInstance().getMQClient();
        client.publish(PropertiesCache.getInstance().get("redis.topic.app"), ByteBufUtil.getBytes(frame.getOnlineEvent()));
    }

    /**
     * 记录设备的上线事件
     * @param macAddress
     */
    private void recodeOnlineEvent(String macAddress){
        OnOffLineEventHistory history = new OnOffLineEventHistory();
        history.setCreateTime(new Date());
        history.setMacAddress(macAddress);
        history.setEventType(EventType.ONLINE.toString());
        BuguDao<OnOffLineEventHistory> dao = DaoCache.getInstance().get(OnOffLineEventHistory.class);
        dao.insert(history);
    }
}
